package DataStructureAndAlgorithm.CSP.Day03;

import java.util.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

//数据量比较大，需要用BufferedReader，不能用Scanner，否则超时

//最优配餐
//多源BFS
//建立超级源点，把所有起点都提前入队列
public class AcWing_3205 {
    //存放所有点的坐标
    static class pair{
        int x;
        int y;
        pair(int x,int y){
            this.x = x;
            this.y = y;
        }
    }

    //存放目标点的坐标和权值
    static class target{
        int x;
        int y;
        int weight;
        target(int x,int y,int weight){
            this.x = x;
            this.y = y;
            this.weight = weight;
        }
    }

    static int n,m,k,d;
    static int N = 1010;
    static boolean[][] st = new boolean[N][N];
    //dist[i][j]：表示从超级源点到点[i,j]的最短距离
    static int[][] dist = new int[N][N];
    //target最多有N * N 个点
    static target[] tg = new target[N * N];
    static Queue<pair> queue = new LinkedList<>();
    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        String s = bf.readLine();
        String[] split = s.split(" ");
        n = Integer.parseInt(split[0]);
        m = Integer.parseInt(split[1]);
        k = Integer.parseInt(split[2]);
        d = Integer.parseInt(split[3]);
        //初始化所有的距离为无穷大
        for (int i = 0; i < N; i++){
            Arrays.fill(dist[i],99999999);
        }
        //读入分店坐标
        for (int i = 0; i < m; i++){
            String s1 = bf.readLine();
            String[] split1 = s1.split(" ");
            int x = Integer.parseInt(split1[0]);
            int y = Integer.parseInt(split1[1]);
            //分店到自己的距离为0
            dist[x][y] = 0;
            //建立超级源点的思路，超级源点能到达所有的分店，且路径为0
            //因此，宽搜的第一层就是把所有的分店入队
            queue.offer(new pair(x,y));
        }
        for (int i = 0; i < k; i++){
            String s1 = bf.readLine();
            String[] split1 = s1.split(" ");
            int x = Integer.parseInt(split1[0]);
            int y = Integer.parseInt(split1[1]);
            int weight = Integer.parseInt(split1[2]);
            tg[i] = new target(x,y,weight);
        }
        for (int i = 0; i < d; i++){
            String s1 = bf.readLine();
            String[] split1 = s1.split(" ");
            int x = Integer.parseInt(split1[0]);
            int y = Integer.parseInt(split1[1]);
            //表示[x,y]点不能通过
            st[x][y] = true;
        }
        BFS();
        long res = 0;
        //把所有点的最短距离累加即为答案
        for (int i= 0; i < k; i++){
            res += dist[tg[i].x][tg[i].y] * tg[i].weight;
        }
        System.out.print(res);
    }

    static void BFS(){
        int[] dx = {-1,0,1,0};
        int[] dy = {0,1,0,-1};
        while (!queue.isEmpty()){
            //拿出队列的第一个元素
            pair temp = queue.poll();
            //访问该元素的相邻位置
            for (int i = 0; i < 4; i++){
                int x = temp.x + dx[i];
                int y = temp.y + dy[i];
                //判断是否移地图外或者点是否不能访问
                if (x < 1 || x > n || y < 1 || y > n || st[x][y])continue;
                //如果距离可以更新
                if (dist[x][y] > dist[temp.x][temp.y] + 1){
                    //更新路径距离，并把新的位置入队
                    dist[x][y] = dist[temp.x][temp.y] + 1;
                    queue.offer(new pair(x,y));
                }
            }
        }
    }
}
